package jmetal.problems.adaboost;


public class WeakClassifier {
	private Feature feature;
	private int xPosition;
	private int yPosition;
	private int width;
	private int height;
	private int polarity;
	private double limiar;
	private double weight;
	
	public WeakClassifier() {
		this.feature = null;
		this.xPosition = 0;
		this.yPosition = 0;
		this.width = 0;
		this.height = 0;
		this.polarity = 1;
		this.limiar = 0;
		this.weight = 0;
	}
	public void init(double type, double x, double y, double w, double h, double l,double p, double wt)
	{
		int tipo = (int) type;
		switch(tipo)
		{
		case 1:
			this.feature = new Feature1();
			break;
		case 2:
			this.feature = new Feature2();
			break;
		case 3:
			this.feature = new Feature3();
			break;
		default:
			this.feature = new Feature4();
		}
		xPosition = (int)x;
		yPosition = (int) y;
		width = (int)w;
		height = (int) h;
		polarity = (int) p;
		limiar = (int) l;
		weight = (int) wt;
	}
	
	public WeakClassifier(int type, double x, double y, double w, double h) {
		switch (type) {
		case 1:
			this.feature = new Feature1();
			break;
		case 2:
			this.feature = new Feature2();
			break;
		case 3:
			this.feature = new Feature3();
			break;
		default:
			this.feature = new Feature4();
			break;
		}

		xPosition = (int) x;
		yPosition = (int) y;
		width = (int) w;
		height = (int) h;
		polarity = 1;
		limiar = 0;
		weight = 0;
	}
	
	public void validate()
	{
		if(feature.getType() < 0)
			feature = new Feature1();
		else if (feature.getType() > 4)
			feature = new Feature4();
		
		if(xPosition > (Config.IMAGE_WIDTH - feature.getMinWidth()))
		{
			xPosition = Config.IMAGE_WIDTH - feature.getMinWidth();
		}
		if(yPosition > (Config.IMAGE_HEIGHT - feature.getMinHeight()))
		{
			yPosition = (Config.IMAGE_HEIGHT - feature.getMinHeight());
		}
		int maxWidth = (Config.IMAGE_WIDTH - xPosition) - ( (Config.IMAGE_WIDTH - xPosition) % feature.getMinWidth());
		if(width > maxWidth)
		{
			width = maxWidth;
		}
		else if(width < feature.getMinWidth())
		{
			width = feature.getMinWidth();
		}
		int maxHeight = (Config.IMAGE_HEIGHT - yPosition) - ( (Config.IMAGE_HEIGHT - yPosition) % feature.getMinHeight());
		if(height > maxHeight)
		{
			height = maxHeight;
		}
		else if(height < feature.getMinHeight())
		{
			height = feature.getMinHeight();
		}
		
		if(polarity >= 0)
		{
			polarity = 1;
		}
		else
		{
			polarity = -1;
		}
	}
	

	public void updatePolarity(Image[] positiveImages,
			int[] positiveTrainningIndex, Image[] negativeImages,
			int[] negativeTrainningIndex) {
		int i;
		int nPositive = positiveImages.length;
		int nNegative = negativeImages.length;
		double mediaPos = 0, mediaNeg = 0;

		for (i = 0; i < nPositive; i++)
			mediaPos += feature.calculateValue(
					positiveImages[positiveTrainningIndex[i]].getMatrix(), this.xPosition,
					this.yPosition, this.width, this.height);

		mediaPos = mediaPos / (nPositive);

		for (i = 0; i < nNegative; i++) {
			mediaNeg += this.feature.calculateValue(
					negativeImages[negativeTrainningIndex[i]].getMatrix(), xPosition, yPosition,
					width, height);

		}
		mediaNeg = mediaNeg / (nNegative);

		if (mediaNeg - mediaPos < 0)
			polarity = -1;
		else
			polarity = 1;

	}
	
	public void setLimiar(Image[] positive, 
			int[] positiveIndex, Image[] negative, 
			int[] negativeIndex) {

		int i;
		int nPositive = positive.length;
		int nNegative = negative.length;
		double mediaPos = 0, mediaNeg = 0;

		for (i = 0; i < nPositive; i++)
			mediaPos += this.feature.calculateValue(
					positive[positiveIndex[i]].getMatrix(), this.xPosition,
					this.yPosition, this.width, this.height);

		mediaPos = mediaPos / (nPositive);

		for (i = 0; i < nNegative; i++) {
			mediaNeg += this.feature.calculateValue(
					negative[negativeIndex[i]].getMatrix(), xPosition, yPosition,
					width, height);

		}
		mediaNeg = mediaNeg / (nNegative);
		limiar = (mediaPos + mediaNeg) / 2;

	}
	
	public int value(Image image) {

		double featureValue = this.feature.calculateValue(image.getMatrix(),
				this.xPosition, this.yPosition, this.width, this.height);

		if ((featureValue * polarity) < (limiar * polarity))
			return 1;
		else
			return 0;
	}
	
	public void classifierToDouble(WeakClassifier classifier, double[] solution,int position) {
		int numParameters = Config.NUMBER_OF_PARAMETERS;
		for (int j = position; j < numParameters; j++)
			switch (j % numParameters) {

			case Config.CLASSIFIER_PARAMETER_FEATURE:
				solution[j] = classifier.getFeature().getType(); //classifier->feature->getType();
				break;

			case Config.CLASSIFIER_PARAMETER_XPOSITION:
				solution[j] = classifier.getxPosition();
				break;

			case Config.CLASSIFIER_PARAMETER_YPOSITION:
				solution[j] = classifier.getyPosition();
				break;

			case Config.CLASSIFIER_PARAMETER_WIDTH:
				solution[j] = classifier.getWidth();
				break;

			case Config.CLASSIFIER_PARAMETER_HEIGHT:
				solution[j] = classifier.getHeight();
				break;

			case Config.CLASSIFIER_PARAMETER_LIMIAR:
				solution[j] = classifier.getLimiar();
				break;

			case Config.CLASSIFIER_PARAMETER_POLARITY:
				solution[j] = classifier.getPolarity();
				break;
			default:
				solution[j] = classifier.getWeight();
				break;

			}
	}
	
	// GETs and SETs
	
	public Feature getFeature() {
		return feature;
	}

	public void setFeature(Feature feature) {
		this.feature = feature;
	}

	public int getxPosition() {
		return xPosition;
	}

	public void setxPosition(int xPosition) {
		this.xPosition = xPosition;
	}

	public int getyPosition() {
		return yPosition;
	}

	public void setyPosition(int yPosition) {
		this.yPosition = yPosition;
	}

	public int getWidth() {
		return width;
	}

	public void setWidth(int width) {
		this.width = width;
	}

	public int getHeight() {
		return height;
	}

	public void setHeight(int height) {
		this.height = height;
	}

	public int getPolarity() {
		return polarity;
	}

	public void setPolarity(int polarity) {
		this.polarity = polarity;
	}

	public double getLimiar() {
		return limiar;
	}

	public void setLimiar(double limiar) {
		this.limiar = limiar;
	}

	public double getWeight() {
		return weight;
	}

	public void setWeight(double weight) {
		this.weight = weight;
	}
	
	
}
